import Konva from "konva";
import { Draw } from "../../../Draw/Draw";
import { setStageCursor } from "./stage-cursor";
import { IKonva } from "../../../Interface/IKonva";
import { KONVA_GRAPH_NAME } from "../../../Config";
import { setGroupDraggable } from "./group-draggable";
import { setGroupTransformer } from "./group-transformer";

/**
 * 监听 stage 鼠标按下事件：
 *  需要识别当前是 插入还是框选，
 *  都需要添加 当前的操作类型 inserting、selecting
 */
export function stageMouseDown(e: IKonva.Event, draw: Draw) {
  e.cancelBubble = true;

  // 仅支持左键框选
  if (e.evt.button !== 0) return;

  const stage = draw.getStage();

  /**
   * 区分是插入形状还是框选
   * 判断是否处于平移阶段
   */
  const { insertShape, translateMode } = stage.attrs;
  if (translateMode) {
    const root = draw.getRootBox();
    const konvaBox = <HTMLElement>(
      root.querySelector(".konva-root-container-konvabox")
    );
    // 继续添加 translating、记录初始位置
    stage.setAttrs({
      translating: true,
      tpx: e.evt.pageX,
      tpy: e.evt.pageY,
      baseStyle: konvaBox.style.transform,
    });
    // 修改 cursor
    setStageCursor(draw, "grab");
    // 这里开始解析 konvaBox 的初始值，需要根据初始值进行加减
  } else if (insertShape) {
    insertHandle(e, draw);
  } else if (e.target.parent?.name() !== KONVA_GRAPH_NAME) {
    // 还要识别拖拽还是框选
    selectHandle(e, draw);
  }
}

// 插入元素事件
function insertHandle(e: IKonva.Event, draw: Draw) {
  const stage = draw.getStage();
  const konvaGraph = draw.getKonvaGraph();

  const { insertShape } = stage.attrs;

  //   记录初始位置
  const ssx = e.evt.offsetX; // stage start x
  const ssy = e.evt.offsetY; // stage start y
  stage.setAttrs({ inserting: true, ssx, ssy });

  let shape = <Konva.Group | Konva.Arrow | null>null;
  function addShape() {
    if (!shape) return;
    konvaGraph.addShape({ shape });
    stage.setAttrs({ insertShapeID: shape.id() });
  }

  /**
   * 在此处生成一个图形，拖拽的时候，是修改它的属性，记录的是ID，通过 ID 唯一寻找元素即可
   *  同时注意：mousedown 不需要 render 因此图形还没有绘制完整，会导致历史记录异常
   */
  switch (insertShape) {
    // 矩形
    case "rect1":
    case "rect2":
    case "rect3":
    case "rect4":
      shape = konvaGraph.Rect({
        width: 1,
        height: 1,
        x: ssx,
        y: ssy,
        cornerRadius: rectCornerRadius(insertShape),
      });
      addShape();
      break;

    // 普通文本
    case "text1":
      shape = konvaGraph.Text({
        x: ssx,
        y: ssy,
        width: 100,
        height: 50,
        text: "请输入文字",
        fontSize: 16,
        fontFamily: "Arial",
        fill: "#000",
      });
      setGroupTransformer(draw, shape);
      konvaGraph.addShape({ shape });
      // 广播
      draw.broadcast({
        type: `${shape.id()}_insert`,
        payload: {
          layerID: draw.getLayer()?.id(),
          insertShape: "text1",
          id: shape.id(),
          x: ssx,
          y: ssy,
        },
      });
      break;

    // 箭头
    case "arrow1":
    case "arrow2":
    case "arrow3":
    case "arrow4":
    case "arrow5":
    case "arrow6":
    case "arrow7":
    case "arrow8":
      shape = konvaGraph.Arrow({
        width: 1,
        height: 1,
        insertShape,
        x: ssx,
        y: ssy,
      });
      addShape();
      break;

    // 线段
    case "line":
    case "line-dash":
      shape = konvaGraph.Line({
        points: [0, 0],
        insertShape,
        dash: insertShape === "line-dash" ? [10, 6] : undefined,
        x: ssx,
        y: ssy,
      });
      addShape();
      break;

    case "line-arrow":
    case "line-arrow-dash":
      shape = konvaGraph.Line({
        points: [0, 0],
        pointerLength: 10,
        pointerWidth: 10,
        insertShape,
        dash: insertShape === "line-arrow-dash" ? [10, 6] : undefined,
        x: ssx,
        y: ssy,
      });
      addShape();
      break;

    // 需要控制点的折线
    case "line-z":
    case "line-zz":
      shape = konvaGraph.Line({
        points: [0, 0],
        pointerLength: 10,
        pointerWidth: 10,
        insertShape,
        x: ssx,
        y: ssy,
      });
      addShape();
      break;

    case "line-w":
    case "line-ww":
      shape = konvaGraph.Line({
        points: [0, 0],
        pointerLength: 10,
        pointerWidth: 10,
        tension: 0.5, // 曲线
        insertShape,
        x: ssx,
        y: ssy,
      });
      addShape();
      break;

    // Logo
    case "logo":
      shape = konvaGraph.Logo({
        width: 1,
        height: 1,
        x: ssx,
        y: ssy,
      });
      addShape();
      break;

    //  五角星
    case "star":
      shape = konvaGraph.Star({
        width: 1,
        height: 1,
        x: ssx,
        y: ssy,
        numPoints: 5,
        innerRadius: 20,
        outerRadius: 40,
      });
      addShape();
      break;

    // 圆环
    case "ring":
      shape = konvaGraph.Ring({
        width: 1,
        height: 1,
        x: ssx,
        y: ssy,
        innerRadius: 20,
        outerRadius: 40,
      });
      addShape();
      break;

    // 圆
    case "circle":
      shape = konvaGraph.Circle({
        width: 1,
        height: 1,
        x: ssx,
        y: ssy,
        radius: 1,
      });
      addShape();
      break;

    // 椭圆
    case "ellipse":
      shape = konvaGraph.Ellipse({
        width: 1,
        height: 1,
        x: ssx,
        y: ssy,
        radiusX: 1,
        radiusY: 1,
      });
      addShape();
      break;

    // 三角形
    case "triangle":
      shape = konvaGraph.Triangle({
        width: 1,
        height: 1,
        x: ssx,
        y: ssy,
      });
      addShape();
      break;

    // 多边形
    case "polygon":
      break;

    default:
      break;
  }

  // 2. 禁止所有元素的拖拽
  setGroupDraggable(draw, false);
}

// 解析矩形圆角
export function rectCornerRadius(insertShape: string) {
  const radius = 20;
  switch (insertShape) {
    case "rect1":
      return [0, 0, 0, 0];
    case "rect2":
      return [radius, radius, radius, radius];
    case "rect3":
      return [radius, radius, 0, 0];
    case "rect4":
      return [radius, 0, radius, 0];
  }
}

// 框选事件
function selectHandle(e: IKonva.Event, draw: Draw) {
  // 如果当前 layer 不存在，则不允许框选
  const layer = draw.getLayer();
  if (!layer) return;

  const stage = draw.getStage();
  const root = draw.getRootBox();
  //   记录初始位置
  const ssx = e.evt.offsetX; // stage start x
  const ssy = e.evt.offsetY; // stage start y
  stage.setAttrs({ selecting: true, ssx, ssy });

  // 修正框选框的位置
  const selectBoxCss = ".konva-root-container-frame_selected";
  const selectBox = <HTMLDivElement>root.querySelector(selectBoxCss);
  selectBox.style.display = "block";
  selectBox.style.left = ssx + "px";
  selectBox.style.top = ssy + "px";
  selectBox.style.opacity = "0";
}
